using System;
using System.Collections.Generic;
using System.Linq;
using Comteck.Dto;
using Comteck.Dto.Common;

namespace Comteck.Winforms.Utils {
  /// <summary>
  /// 日期切片方式
  /// </summary>
  public class DateSplitModeBusiness {
    /// <summary>
    /// 计算查询日期周期
    /// </summary>
    /// <param name="startDate"></param>
    /// <param name="endDate"></param>
    /// <param name="dateSplitMode"></param>
    /// <returns></returns>
    public static List<DateRange> Calculate(DateTime startDate, DateTime endDate, int dateSplitMode) {
      // result
      var result = new List<DateRange>();

      // 日期模式
      var dateMode = (EnumDateSplitMode) dateSplitMode;

      switch (dateMode) {
        case EnumDateSplitMode.不切片: {
            result.Add(new DateRange(startDate, endDate));
          }
          break;
        case EnumDateSplitMode.日报切片: {
            var startDate1 = startDate;
            var endDate1 = endDate;
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddDays(1).AddDays(-1);
              result.Add(new DateRange(date1, date2));

              startDate1 = startDate1.AddDays(1);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.周报切片: {
            var startDate1 = startDate.AddDays(1 - ((int) startDate.DayOfWeek == 0 ? 7 : (int) startDate.DayOfWeek));
            var endDate1 = endDate.AddDays(1 - ((int) endDate.DayOfWeek == 0 ? 7 : (int) endDate.DayOfWeek)).AddDays(7).AddDays(-1);
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddDays(7).AddDays(-1);
              result.Add(new DateRange(date1, date2));

              startDate1 = startDate1.AddDays(7);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.月报切片: {
            var startDate1 = new DateTime(startDate.Year, startDate.Month, 1);
            var endDate1 = new DateTime(endDate.Year, endDate.Month, 1).AddMonths(1).AddDays(-1);
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddMonths(1).AddDays(-1);
              result.Add(new DateRange(date1, date2));

              startDate1 = startDate1.AddMonths(1);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.季报切片: {
            var seasonStartMonth = (startDate.Month - 1) / 3 * 3 + 1;
            var startDate1 = new DateTime(startDate.Year, seasonStartMonth, 1);
            var seasonEndMonth = (endDate.Month - 1) / 3 * 3 + 3;
            var endDate1 = new DateTime(endDate.Year, seasonEndMonth, 1).AddMonths(1).AddDays(-1);

            do {
              var date1 = startDate1;
              var date2 = startDate1.AddMonths(3).AddDays(-1);
              result.Add(new DateRange(date1, date2));

              startDate1 = startDate1.AddMonths(3);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.年报切片: {
            var startDate1 = new DateTime(startDate.Year, 1, 1);
            var endDate1 = new DateTime(endDate.Year, 12, 1).AddMonths(1).AddDays(-1);
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddMonths(12).AddDays(-1);
              result.Add(new DateRange(date1, date2));

              startDate1 = startDate1.AddMonths(12);
            } while (startDate1 <= endDate1);
          }
          break;
        default:
          break;
      }

      // 单独处理第一条
      var first = result.FirstOrDefault();
      if (first != null) {
        first.StartDate = first.StartDate < startDate ? startDate : first.StartDate;
      }

      // 单独最后第一条
      var last = result.LastOrDefault();
      if (last != null) {
        last.EndDate = last.EndDate > endDate ? endDate : last.EndDate;
      }

      return result;
    }

    /// <summary>
    /// 计算查询日期周期
    /// </summary>
    /// <param name="startDate"></param>
    /// <param name="endDate"></param>
    /// <param name="dateSplitMode"></param>
    /// <returns></returns>
    public static List<DateOnlySplitRange> Calculate(DateOnly startDate, DateOnly endDate, EnumDateSplitMode dateSplitMode) {
      return Calculate(startDate, endDate, (int) dateSplitMode);
    }

    /// <summary>
    /// 计算查询日期周期
    /// </summary>
    /// <param name="startDate"></param>
    /// <param name="endDate"></param>
    /// <param name="dateSplitMode"></param>
    /// <returns></returns>
    public static List<DateOnlySplitRange> Calculate(DateOnly startDate, DateOnly endDate, int dateSplitMode) {
      // result
      var result = new List<DateOnlySplitRange>();

      // 日期模式
      var dateMode = (EnumDateSplitMode) dateSplitMode;

      switch (dateMode) {
        case EnumDateSplitMode.不切片: {
            result.Add(new DateOnlySplitRange(startDate, endDate));
          }
          break;
        case EnumDateSplitMode.日报切片: {
            var startDate1 = startDate;
            var endDate1 = endDate;
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddDays(1).AddDays(-1);
              result.Add(new DateOnlySplitRange(date1, date2));

              startDate1 = startDate1.AddDays(1);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.周报切片: {
            var startDate1 = startDate.AddDays(1 - ((int) startDate.DayOfWeek == 0 ? 7 : (int) startDate.DayOfWeek));
            var endDate1 = endDate.AddDays(1 - ((int) endDate.DayOfWeek == 0 ? 7 : (int) endDate.DayOfWeek)).AddDays(7).AddDays(-1);
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddDays(7).AddDays(-1);
              result.Add(new DateOnlySplitRange(date1, date2));

              startDate1 = startDate1.AddDays(7);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.月报切片: {
            var startDate1 = new DateTime(startDate.Year, startDate.Month, 1);
            var endDate1 = new DateTime(endDate.Year, endDate.Month, 1).AddMonths(1).AddDays(-1);
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddMonths(1).AddDays(-1);
              result.Add(new DateOnlySplitRange(date1.ToDateOnly(), date2.ToDateOnly()));

              startDate1 = startDate1.AddMonths(1);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.季报切片: {
            var seasonStartMonth = (startDate.Month - 1) / 3 * 3 + 1;
            var startDate1 = new DateTime(startDate.Year, seasonStartMonth, 1);
            var seasonEndMonth = (endDate.Month - 1) / 3 * 3 + 3;
            var endDate1 = new DateTime(endDate.Year, seasonEndMonth, 1).AddMonths(1).AddDays(-1);

            do {
              var date1 = startDate1;
              var date2 = startDate1.AddMonths(3).AddDays(-1);
              result.Add(new DateOnlySplitRange(date1.ToDateOnly(), date2.ToDateOnly()));

              startDate1 = startDate1.AddMonths(3);
            } while (startDate1 <= endDate1);
          }
          break;
        case EnumDateSplitMode.年报切片: {
            var startDate1 = new DateTime(startDate.Year, 1, 1);
            var endDate1 = new DateTime(endDate.Year, 12, 1).AddMonths(1).AddDays(-1);
            do {
              var date1 = startDate1;
              var date2 = startDate1.AddMonths(12).AddDays(-1);
              result.Add(new DateOnlySplitRange(date1.ToDateOnly(), date2.ToDateOnly()));

              startDate1 = startDate1.AddMonths(12);
            } while (startDate1 <= endDate1);
          }
          break;
        default:
          break;
      }

      // 单独处理第一条
      var first = result.FirstOrDefault();
      if (first != null) {
        first.Begin_Date = first.Begin_Date < startDate ? startDate : first.Begin_Date;
      }

      // 单独最后第一条
      var last = result.LastOrDefault();
      if (last != null) {
        last.End_Date = last.End_Date > endDate ? endDate : last.End_Date;
      }

      return result;
    }
  }

  /// <summary>
  /// 通用的日期范围
  /// </summary>
  public class DateOnlySplitRange {
    /// <summary>
    /// 开始日期
    /// </summary>
    public DateOnly Begin_Date { get; set; }

    /// <summary>
    /// 开始日期
    /// </summary>
    public DateOnly End_Date { get; set; }

    /// <summary>
    /// 
    /// </summary>
    public DateOnlySplitRange() {
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="beginDate"></param>
    /// <param name="endDate"></param>
    public DateOnlySplitRange(DateOnly beginDate, DateOnly endDate) : this(){
      this.Begin_Date = beginDate;
      this.End_Date = endDate;
    }
  }
}
